package me.edzh.spring.bootstrap.interceptor;

import lombok.extern.log4j.Log4j;
import lombok.var;
import me.edzh.spring.bootstrap.utils.Constants;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * Created by Edward
 * 2016/8/13.
 */
@Log4j
public class TraceIdInterceptor extends HandlerInterceptorAdapter {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        MDC.clear();
        MDC.put(Constants.LOG_TRACE_ID, UUID.randomUUID().toString());
        String remoteIp = request.getHeader("X-Forwarded-For");
        String ua = request.getHeader("ua");
        String version = request.getHeader("VERSION");
        String os = request.getHeader("OS");
        MDC.put(Constants.REMOTE_IP, remoteIp == null ? "192.168.0.1" : remoteIp);
        MDC.put(Constants.REQ_START_TIME, System.currentTimeMillis());

        if (request.getHeader(Constants.DEVICE_ID) != null) {
            MDC.put(Constants.DEVICE_ID, request.getHeader(Constants.DEVICE_ID));

        }

        if (request.getHeader(Constants.GPS) != null) {
            MDC.put(Constants.GPS, request.getHeader(Constants.GPS));
        }

        if (request.getHeader(Constants.LOCALIZATION) != null) {
            MDC.put(Constants.LOCALIZATION, request.getHeader(Constants.LOCALIZATION));
        }

        if (request.getHeader(Constants.DEVICE_TYPE) != null) {
            MDC.put(Constants.DEVICE_TYPE, request.getHeader(Constants.DEVICE_TYPE));

        }
        if (handler instanceof HandlerMethod) {
            var hand = (HandlerMethod)handler;
            String methodName = hand.getMethod().getDeclaringClass().getSimpleName() + "." + hand.getMethod().getName();
            MDC.put(Constants.REQ_HANDLER, methodName);
        }



        if (!"/alive".equals(request.getRequestURI())) {
            StringBuilder sb = new StringBuilder();
            sb.append(request.getMethod());
            sb.append(" ");
            sb.append(request.getRequestURI());
            sb.append("[");
            sb.append(remoteIp);
            sb.append("][");
            sb.append(Constants.getCurrentDeviceId());
            sb.append("][");
            sb.append(Constants.getCurrentGPS());
            sb.append("][");
            sb.append(os);
            sb.append("][");
            sb.append(version);
            sb.append("][");
            sb.append(ua);
            sb.append("]");
            log.info(sb.toString());
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if (!"/alive".equals(request.getRequestURI())) {
            logRequestTimeCost(true);
        }


        MDC.clear();
    }

    public static void logRequestTimeCost(boolean succeeded) {
        Long startTime = (Long) MDC.get(Constants.REQ_START_TIME);
        long cost = System.currentTimeMillis() - startTime;
        String methodName = Constants.getCurrentHandlerName();
        log.warn("REQ_TIME_COST:[" + methodName + "][" + cost + "]" + "[" + (succeeded ? "SUCC" : "FAIL") + "]");
    }
}